/**
访问者模式（Visitor Pattern）

意图：主要将数据结构与数据操作分离。
主要解决：稳定的数据结构和易变的操作耦合问题。
何时使用：需要对一个对象结构中的对象进行很多不同的并且不相关的操作，而需要避免让这些操作"污染"这些对象的类，使用访问者模式将这些封装到类中。
如何解决：在被访问的类里面加一个对外提供接待访问者的接口。
*/
main(List<String> args) {
  ComputerPart computer = Computer();
  computer.accept(ComputerPartDisplayVisitor());
}

//////////////////////////////////////////////////////////////////

///
/// 定义一个表示元素的接口
///
abstract class ComputerPart {
  void accept(ComputerPartVisitor computerPartVisitor);
}

///
/// 创建扩展了上述类的实体类
///
class Keyboard implements ComputerPart {
  @override
  void accept(ComputerPartVisitor computerPartVisitor) {
    computerPartVisitor.visit(this);
  }
}

class Monitor implements ComputerPart {
  @override
  void accept(ComputerPartVisitor computerPartVisitor) {
    computerPartVisitor.visit(this);
  }
}

class Mouse implements ComputerPart {
  @override
  void accept(ComputerPartVisitor computerPartVisitor) {
    computerPartVisitor.visit(this);
  }
}

class Computer implements ComputerPart {
  List<ComputerPart> _parts;

  Computer() {
    _parts = [Mouse(), Keyboard(), Monitor()];
  }

  @override
  void accept(ComputerPartVisitor computerPartVisitor) {
    for (int i = 0; i < _parts.length; i++) {
      _parts[i].accept(computerPartVisitor);
    }
    computerPartVisitor.visit(this);
  }
}

///
/// 定义一个表示访问者的接口
///
abstract class ComputerPartVisitor {
  void visit(dynamic part);
}

///
/// 创建实现了上述类的实体访问者
///
class ComputerPartDisplayVisitor implements ComputerPartVisitor {
  @override
  void visit(part) {
    if (part is Computer) {
      print("Displaying Computer.");
    } else if (part is Mouse) {
      print("Displaying Mouse.");
    } else if (part is Keyboard) {
      print("Displaying Keyboard.");
    } else if (part is Monitor) {
      print("Displaying Monitor.");
    }
  }
}
